package com.helloniu.util;

import java.awt.Color;
import java.util.Date;
import org.apache.mina.common.ByteBuffer;
import org.red5.io.amf3.ByteArray;
import com.gnetis.tang.whiteboard.WhiteboardObject;
import com.gnetis.tang.whiteboard.util.Base64;

/**
 * Tool is a util class for whiteboard.
 *
 * @version     0.1, 10/21/08
  */
public class Tool {
    /** Mark the object is null. */
    private static byte TANG_NULL = 0;
    /** Mark the object is not null. */
    private static byte TANG_OBJECT = 1;

    /**
     * Write a date object to byte array.
     *
     * @param output a Writer object to write the data.
     * @param date the data to be writen.
     */
    public static void writeDate(ByteArray output, Date date) {
        if(date == null) {
            output.writeByte(TANG_NULL);
        }
        else {
            output.writeByte(TANG_OBJECT);
            double ms = date.getTime();
            output.writeDouble(ms);
        }
    }

    /**
     * Read date object from byte array.
     *
     * @param input an input object to get the data.
     */
    public static Date readDate(ByteArray input) {
        byte b = input.readByte();

        if(b == TANG_NULL) {
           return null;
        }

        long ms = (long) input.readDouble();
        Date date = new Date(ms);

        return date;
    }

    /**
     * Write a date object to byte array.
     *
     * @param output a Writer object to write the data.
     * @param obj the data to be writen.
     */
    public static void writeObject(ByteArray output, WhiteboardObject obj) {
        if(obj == null) {
            output.writeByte(TANG_NULL);
        }
        else {
            output.writeByte(TANG_OBJECT);
            output.writeUTF(obj.getClass().getName());
            obj.writeData(output);

        }
    }

    /**
     * Read object object from byte array.
     *
     * @param input an input object to get the data.
     */
    public static WhiteboardObject readObject(ByteArray input) {
        byte b = input.readByte();
        WhiteboardObject obj = null;

        if(b == TANG_NULL) {
           return obj;
        }

        String clazz = input.readUTF();

        try {
            obj = (WhiteboardObject) Class.forName(clazz).newInstance();
            obj.readData(input);
        }
        catch(Exception ex) {
            // @temp tonyy
            // log the error ? or do sth?
            throw new RuntimeException(ex);
        }

        return obj;
    }

    /**
     * Write a date object to byte array.
     *
     * @param output a Writer object to write the data.
     * @param arr the data to be writen.
     */
    public static void writeArray(ByteArray output, Object[] arr) {
        if(arr == null || arr.length == 0) {
            output.writeInt(0);
        }
        else {
            output.writeInt(arr.length);

            for(int i = 0; i < arr.length; i++) {
                if(!(arr[i] instanceof WhiteboardObject)) {
                    throw new RuntimeException("Unexpected object found: " + arr[i]);
                }

                WhiteboardObject obj = (WhiteboardObject) arr[i];
                writeObject(output, obj);
            }
        }
    }

    /**
     * Read object object from byte array.
     *
     * @param input an input object to get the data.
     */
    public static Object[] readArray(ByteArray input) {
        int arrLength = input.readInt();
        Object[] arr = new Object[arrLength];

        if(arrLength == 0) {
           return arr;
        }

        for(int i = 0; i < arrLength; i++) {
            arr[i] = readObject(input);
        }

        return arr;
    }

    /**
     * Convert an object to base64-encoded characters.
     */
    public static String objectToString(WhiteboardObject obj) {
        ByteArray barr = new ByteArray();
        obj.writeData(barr);
        // @temp tonyy, for performance
        barr.compress();
        barr.position(0);

        byte[] bytes = new byte[barr.length()];
        barr.readBytes(bytes);
        String javaEncode = Base64.encode(bytes);

        return javaEncode;
    }


    /**
     * Convert a base64-encoded characters to object.
     */
    public static void stringToObject2(WhiteboardObject obj, String str) {
        byte[] deBytes = Base64.decode(str);
        ByteBuffer data = ByteBuffer.allocate(deBytes.length);
        data.put(deBytes);
        data.flip();
        ByteArray barr = new ByteArray(data, deBytes.length);
        barr.uncompress();

        obj.readData(barr);
    }


    /**
     * Write a color object to byte array.
     *
     * @param output a Writer object to write the data.
     * @param color the data to be writen.
     */
    public static void writeColor(ByteArray output, Color color){
        output.writeInt(color.getRed());
        output.writeInt(color.getGreen());
        output.writeInt(color.getBlue());
        output.writeInt(color.getAlpha());
    }

    /**
     * Read color object from byte array.
     *
     * @param input an input object to get the data.
     */
    public static Color readColor(ByteArray input) {
        int r = input.readInt();
        int g = input.readInt();
        int b = input.readInt();
        int a = input.readInt();

        return new Color(r, g, b, a);
    }
}
